#ifndef MAZETYPES_H
#define MAZETYPES_H

#include "GraphNode.h"
#include "D3DXVECTOROperators.h"
#include "ConstantBuffer.h"
#include "OOBB3Collision.h"

#include <map>
#include <vector>
#include <D3DX11.h>

enum CellWall
{
	NO_WALL = 0x00,
	NORTH = 0x01,
	EAST = 0x02,
	SOUTH = 0x04,
	WEST = 0x08
};

enum PositionType
{
	NO_TYPE = 0x00,
	TOP = 0x01,
	BOT = 0x002,
	RIGHT = 0x04,
	LEFT = 0x08,
	CENTRE = 0x10
};

enum CellType
{
	ROOM = 0x00,
	VERTICAL_DOOR = 0x01,
	HORIZONTAL_DOOR = 0x02,
	WALL = 0x04,
	CORNER = 0x08,
	PATH = 0x10,
	EMPTY = 0x20,
	EDGE = 0x40,
	ROOM_EDGE = 0x80,
	ROOM_CORNER = 0x100
};

typedef std::map<CellWall, bool> CellWalls; // <Wall, isOpen>
typedef std::pair<PositionType, CellWall> AvailableDoors;

class Cell : public GraphNode
{
public:
	Cell();

	void Draw();

	// may not need and can return the available doors pair instead
	//bool GetCellWall(CellWall wall) const;
	//void SetCellWall(CellWall wall, bool isOpen);

	PositionType GetPosType() const;
	void SetPosType(PositionType ptype);

	CellWall GetCellWalls() const; // e.g. if this cell is a TOP|RIGHT then ths returns east and south doors
	CellWall GetAvailableWalls() const; // returns currently available walls/doors
	void RemoveAvailableWall(CellWall wall);

	void RemoveRoomWall(CellWall wall);
	CellWall GetRoomWalls() const;

	void SetSouthWallPosition(const D3DXVECTOR3& pos);
	D3DXVECTOR3 GetSouthWallPosition() const;

	void SetWestWallPosition(const D3DXVECTOR3& pos);
	D3DXVECTOR3 GetWestWallPosition() const;

	void SetNorthWallPosition(const D3DXVECTOR3& pos);
	D3DXVECTOR3 GetNorthWallPosition() const;

	void SetEastWallPosition(const D3DXVECTOR3& pos);
	D3DXVECTOR3 GetEastWallPosition() const;

	void SetCellType(CellType type);
	CellType GetCellType() const;

	OOBB3& GetOOBB();

private:
	CellType m_cellType;
	CellWalls m_cellWalls;
	float m_size;
	PositionType m_posType;
	AvailableDoors m_availableDoors;
	CellWall m_nonOpenedWalls; //opened doors
	D3DXVECTOR3 m_positionSouth;
	D3DXVECTOR3 m_positionWest;
	D3DXVECTOR3 m_positionNorth;
	D3DXVECTOR3 m_positionEast;

	// draw vars
	ID3D11Buffer* m_pVertexBuffer;
	ID3D11Buffer* m_pIndexBuffer;
	ID3D11Buffer* m_pConstantBuffer;
	
	ConstantBuffer m_cb;

	D3DXMATRIX m_world;

	int m_numOfIndices;
	std::string m_shaderName;
	D3DXVECTOR4 m_colour;

	CellWall m_roomWalls;

	OOBB3 m_oobb;
};

typedef std::pair<int, int> CellPosition; // CellPosition != 3d position of cell
typedef std::map<CellPosition, Cell> Grid;
typedef std::map<int, std::vector<CellPosition>> RoomsCells;
typedef std::pair<int, int> RoomSize;

struct JoiningDoorCells
{
	JoiningDoorCells()
	{
		room[0] = -1;
		room[1] = -1;
		position[0] = CellPosition(-1, -1);
		position[1] = CellPosition(-1, -1);
	}

	CellPosition position[2];
	int room[2];
};

struct MazeDisplayInfo
{
	float timeToGenerate;
};

struct CellColour
{
	CellColour()
	{
		r = 0.0f;
		g = 0.0f;
		b = 0.0f;
	}
	CellColour(float red)
	{
		r = red;
		g = 0;
		b = 0;
	}

	float r;
	float g;
	float b;
};

#endif //MAZETYPES_H